package com.study.mike.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.study.mike.common.constants.Constant;
import com.study.mike.common.constants.RedisKey;
import com.study.mike.common.exception.BizException;
import com.study.mike.mapper.MagicalLandMapper;
import com.study.mike.model.dto.ImportMagicLandInfoListener;
import com.study.mike.model.dto.MagicalLandDTO;
import com.study.mike.model.dto.PageDTO;
import com.study.mike.model.entity.MagicalLandDO;
import com.study.mike.model.po.DeleteMagicalPO;
import com.study.mike.model.po.MagicLandImportPO;
import com.study.mike.model.po.MagicalLandPO;
import com.study.mike.model.po.MagicalQueryPO;
import com.study.mike.service.MagicalLandService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author KangHui
 * @Date 2022/12/23 16:26
 */
@Service
@CacheConfig(cacheNames = RedisKey.TWO_HOUR)
@Slf4j
public class MagicalLandServiceImpl extends ServiceImpl<MagicalLandMapper, MagicalLandDO> implements MagicalLandService {
    @Resource
    private MagicalLandMapper magicalLandMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(allEntries = true)
    public Boolean addMagical(MagicalLandPO magicalLandPO) {
        return operationData(magicalLandPO);
    }

    @Override
    @CacheEvict(allEntries = true)
    public Boolean updateMagical(MagicalLandPO po) {
        return operationData(po);
    }

    @Override
    @Cacheable(key = "#root.methodName + #po.pageCurrent + #po.pageSize")
    public PageDTO<MagicalLandDO> queryMagical(MagicalQueryPO po) {
        LambdaQueryWrapper<MagicalLandDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StrUtil.isNotBlank(po.getGameNo()), MagicalLandDO::getGameNo, po.getGameNo())
                .like(StrUtil.isNotBlank(po.getGameName()), MagicalLandDO::getGameName, po.getGameName())
                .like(StrUtil.isNotBlank(po.getArthur()), MagicalLandDO::getArthur, po.getArthur())
                .like(StrUtil.isNotBlank(po.getDevelopCompany()), MagicalLandDO::getDevelopCompany, po.getDevelopCompany());
        PageDTO<MagicalLandDO> page = new PageDTO<>(po.getPageCurrent(), po.getPageSize());
        IPage pages = this.page(page, wrapper);
        page.setRecords(pages.getRecords());
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(allEntries = true)
    public Boolean deleteMagicalBatch(DeleteMagicalPO po) {
        // 获取数据id列表
        List<Long> ids = po.getMagicalLandPOS().stream().map(MagicalLandPO::getId).collect(Collectors.toList());
        // 获取编号列表
        List<String> nos = po.getMagicalLandPOS().stream().map(MagicalLandPO::getGameNo).collect(Collectors.toList());
        // 优先采用id去做数据移除操作
        if (CollUtil.isNotEmpty(ids)) {
            return magicalLandMapper.deleteBatchIds(ids) > 0;
        }
        // 采用编号去做处理
        for (String item : nos) {
            LambdaQueryWrapper<MagicalLandDO> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(MagicalLandDO::getId, item);
            int delete = magicalLandMapper.delete(wrapper);
            if (delete == 0) {
                log.error(item + "数据删除失败");
                continue;
            }
        }
        return true;
    }

    @Override
    public Boolean exportMagicLand(MagicalQueryPO po) {
        // 获取到导出的数据
        List<MagicalLandDTO> magicalLandDTOS = new ArrayList<>(10);
        // 当前页
        if (ObjectUtil.equal(Constant.ExportType.CURRENT, po.getExportType())) {
            List<MagicalLandDO> records = this.queryMagical(po).getRecords();
            magicalLandDTOS = JSONUtil.toList(JSONUtil.toJsonStr(records), MagicalLandDTO.class);
        }
        if (ObjectUtil.equal(Constant.ExportType.SELECT, po.getExportType())) {
            magicalLandDTOS = this.queryMagicalLandInfo(po);
        }
        if (ObjectUtil.equal(Constant.ExportType.ALL, po.getExportType())) {
            magicalLandDTOS = this.queryMagicalLandInfo(po);
        }
        if (CollUtil.isEmpty(magicalLandDTOS)) {
            return false;
        }
        // 处理数据
        String path = Constant.ExportFilePath.MAGICAlAND;
        EasyExcel.write(path, MagicalLandDTO.class).sheet().doWrite(magicalLandDTOS);
        return true;
    }

    @Override
    public Boolean importMagicLand() {
        ImportMagicLandInfoListener importMagicLandInfoListener = new ImportMagicLandInfoListener();
        String filePath = Constant.ExportFilePath.IMPORTMAGICAlAND;
        EasyExcel.read(filePath, MagicLandImportPO.class, importMagicLandInfoListener).sheet().doRead();
        List<MagicLandImportPO> magicalDTOs = importMagicLandInfoListener.getMagicalDTOs();
        // 对数据转化
        List<MagicalLandDO> magicalLandDTOS = new ArrayList<>(10);
        magicalDTOs.forEach(x -> {
            MagicalLandDO magicalLandDO = new MagicalLandDO();
            BeanUtils.copyProperties(x, magicalLandDO);
            try {
                magicalLandDO.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(x.getCreateTime()));
                magicalLandDO.setIssueTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(x.getIssueTime()));
                magicalLandDO.setUpdateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(x.getUpdateTime()));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            magicalLandDO.setSalePrice(new BigDecimal(x.getSalePrice()));
            magicalLandDTOS.add(magicalLandDO);
        });
        for (MagicalLandDO magicalLandDO : magicalLandDTOS) {
            try {
                this.save(magicalLandDO);
            } catch (Exception e) {
                log.info("当前数据导入失败");
                continue;
            }
        }
        return true;
    }

    public List<MagicalLandDTO> queryMagicalLandInfo(MagicalQueryPO po) {
        LambdaQueryWrapper<MagicalLandDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(ObjectUtil.isNotNull(po.getIds()), MagicalLandDO::getId, po.getIds());
        List<MagicalLandDO> list = this.list(wrapper);
        List<MagicalLandDTO> magicalLandDTOS = JSONUtil.toList(JSONUtil.toJsonStr(list), MagicalLandDTO.class);
        return magicalLandDTOS;
    }

    private Boolean operationData(MagicalLandPO magicalLandPO) {
        MagicalLandDO magicalLandDO = new MagicalLandDO();
        BeanUtils.copyProperties(magicalLandPO, magicalLandDO);
        try {
            return this.saveOrUpdate(magicalLandDO);
        } catch (DuplicateKeyException e) {
            if (ObjectUtil.isNotEmpty(magicalLandDO)) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            }
            throw new BizException("400", "编号已存在，请核实！");
        }
    }
}
